#!/usr/bin/env node
const webpack = require("webpack");
const { spawn } = require("child_process");
const path = require("path");
const WebpackDevServer = require("webpack-dev-server");
const { Command } = require("commander");
let clientConfig = require("./config/webpack.config");
let rendererConfig = require("./config/webpack.renderer");

let program = new Command();
program.name("chrome编译插件");
program.description("这个工具可以帮助你快速构建");
program.option("-s, --start", "启动开发服务器，并且启动app");
// 初始化命令
program.action((args) => {
  let start = args.start;
  if (start) {
    startDevServer(clientConfig, rendererConfig);
  } else {
    build(clientConfig);
    build(rendererConfig);
  }
});
program.parse();

/**
 * 打包编译
 * @param {Object} config 配置项
 * @param {string} name 名称
 */
function build(config) {
  webpack(config, (err, stats) => {
    if (err || stats.hasErrors()) {
      console.log(
        err ||
          stats.toString({
            preset: "errors-only",
            colors: true,
          })
      );
      return;
    }
  });
}

/**
 * 开启开发模式
 * @param {Object} clientConfig 客户端配置
 * @param {Object} rendererConfig  服务器端配置
 */
async function startDevServer(clientConfig, rendererConfig) {
  let clientCompiled = false;
  const ccompiler = webpack(clientConfig);
  const rcompiler = webpack(rendererConfig);
  let runContext = null;
  const server = new WebpackDevServer(
    {
      ...clientConfig.devServer,
      hot: true,
      devMiddleware: {
        writeToDisk: true,
      },
    },
    ccompiler
  );
  ccompiler.hooks.done.tap("WEBPACK_SETUP", () => {
    clientCompiled = true;
    openInApp();
  });
  // 启动开发服务器
  server.startCallback((err) => {
    if (err) return console.error("[System] DevServer start error: ", err);
    console.log("[System] DevServer started successfully");
  });
  // 监听服务器端和客户端的修改启动app
  rcompiler.watch(
    {
      aggregateTimeout: 100,
    },
    () => {
      if(clientCompiled){
        openInApp();
      }
    }
  );
  /**
   * 重新打开App窗口，如果已经打开则不处理
   * @returns 
   */
  function openInApp() {
    if (runContext) return;
    console.log("\n App Open!");
    runContext = spawn(
      process.platform === "win32" ? "npx.cmd" : "npx",
      ["electron", path.resolve(rcompiler.outputPath, "main.js")],
      {
        cwd: rcompiler.outputPath,
      }
    );
    runContext.stdout.pipe(process.stdout);
    runContext.stderr.pipe(process.stderr);
    runContext.on("close", () => {
      runContext = null;
      console.log("\n App Close!");
    });
    runContext.on("exit", () => {
      runContext = null;
      console.log("\n App Exit!");
    });
    runContext.on("disconnect", () => {
      runContext = null;
      console.log("\n App Disconnect!");
    });
  }
}
